﻿''' <summary>
''' Represents the interpreter's default command set.
''' </summary>
''' <remarks></remarks>
Public Class DefaultCommands

    <CommandMethod("Sets the text color, or back color if backColor = True.", "Sets the text color or back color to a valid ConsoleColor, specified by name or number. Use TRUE as a second parameter to set the back color instead of the text color.\[n2]\[r5]Colors\[n1]\[r5]\[c0]\[b15]Color  0\[b16] \[c1]Color  1 \[c2]Color  2 \[c3]Color  3 \[c4]Color  4 \[c5]Color  5 \[c6]Color  6 \[c7]Color  7\[n1]\[r5]\[c8]Color  8 \[c9]Color  9 \[c10]Color 10 \[c11]Color 11 \[c12]Color 12 \[c13]Color 13 \[c14]Color 14 \[c15]Color 15\[c16]")>
    <CommandMethodArgument("Color", 0, "The console color to use; either the name of the color in proper-case, or the color's numeric id (0-15).  Use any other number to reset to default.")>
    <CommandMethodArgument("BackColor", 1, "(Optional) Boolean (True/False) value which determines if the color applies to the text or back color. Use True to set the back color.")>
    Public Overridable Sub SetColor(line As CommandLine)
        If line.Words.Length > 1 Then
            Dim testColor As String = line.Words(1).Word.Trim
            Dim colorValue As ConsoleColor
            If [Enum].TryParse(Of ConsoleColor)(testColor, True, colorValue) Then
                If colorValue > 15 OrElse colorValue < 0 Then
                    colorValue = ConsoleColor.Gray
                End If
                Dim backColor As Boolean = False
                If line.Words.Length > 2 Then
                    Boolean.TryParse(line.Words(2).Word.Trim, backColor)
                End If
                If backColor Then
                    Console.BackgroundColor = colorValue
                Else
                    Console.ForegroundColor = colorValue
                End If
            Else
                line.SetResultMessage("Invalid ConsoleColor: " & testColor, True)
            End If
        Else
            line.SetResultMessage("Color not specified.", False)
        End If
    End Sub

    <CommandMethod("Exits the program.", "Allows the program to end, closing the console window.  Same as the \[c9]Exit\[c16] command.")>
    Public Overridable Sub Quit(line As CommandLine)
        CommandInterpreter._IsRunning = False
        line.SetResultMessage("Exiting program...", False)
    End Sub

    <CommandMethod("Exits the program.", "Allows the program to end, closing the console window.  Same as the \[c9]Quit\[c16] command.")>
    Public Sub [Exit](line As CommandLine)
        Quit(line)
    End Sub

    <CommandMethod("Displays available commands, or info on a specific command.", "Follow help with a command name to get help for the specific command (if available).", "?")>
    <CommandMethodArgument("CommandName", 0, "(Optional) Displays help for the specified command, if available.")>
    Public Overridable Sub Help(line As CommandLine)
        If line.Words.Length = 1 Then
            Dim stopCounting As Boolean = False
            Dim lineCount As Integer = 1
            ConsoleOutput.WriteFormatted("Type help followed by a command name to receive help on the specific command, if available.\[n2]The following commands are available:\[n]")
            Dim commandNames As New SortedSet(Of String)
            For Each commandMethod As RegisteredCommandMethod In CommandInterpreter.Registration
                If Not commandMethod.IsHidden Then
                    commandNames.Add(commandMethod.CommandName)
                End If
            Next
            For Each commandName As String In commandNames
                Dim commandMethod As RegisteredCommandMethod = CommandInterpreter.Registration(commandName)
                ConsoleOutput.WriteFormatted("\[r3]\[c14]{0}\[c16] ({1})\[n]", commandMethod.CommandName, commandMethod.Description)
                lineCount += 1
                If Not stopCounting AndAlso lineCount >= Console.WindowHeight - 2 Then
                    ConsoleOutput.WriteColored(ConsoleColor.DarkGray, False, "(more...)")
                    If Console.ReadKey(True).Key = ConsoleKey.Escape Then
                        stopCounting = True
                    End If
                    Console.CursorLeft = 0
                    Console.Write("         ")
                    Console.CursorLeft = 0
                    lineCount = 0
                End If
            Next
        Else
            Dim testName As String = line.Words(1).Word.Trim
            If CommandInterpreter.Registration.Contains(testName) Then
                Dim commandMethod As RegisteredCommandMethod = CommandInterpreter.Registration(testName)
                If Not commandMethod.IsHidden Then
                    Dim argBuilder As New System.Text.StringBuilder
                    For Each argAttrib As CommandMethodArgumentAttribute In commandMethod.ArgumentAttributes
                        If argBuilder.Length > 0 Then argBuilder.Append(" ")
                        argBuilder.Append("[")
                        argBuilder.Append(argAttrib.ArgumentName)
                        argBuilder.Append("]")
                    Next
                    ConsoleOutput.WriteFormatted("\[r3]\[c14]{0} \[c6]X\[c16]\[n]\[r5]{1}\[n2]".Replace("X", argBuilder.ToString), commandMethod.CommandName, commandMethod.Description)
                    If commandMethod.MethodAttribute.AlternateNames.Length > 0 Then
                        ConsoleOutput.WriteFormatted("\[r5] Alternative: ")
                        For index As Integer = 0 To commandMethod.MethodAttribute.AlternateNames.Length - 1
                            ConsoleOutput.WriteFormatted("\[c14]{0}\[c16]", commandMethod.MethodAttribute.AlternateNames(index))
                            If index < commandMethod.MethodAttribute.AlternateNames.Length - 1 Then
                                ConsoleOutput.Write(", ")
                            End If
                        Next
                        ConsoleOutput.WriteLine(2)
                    End If
                    If commandMethod.ArgumentAttributes.Length > 0 Then
                        ConsoleOutput.WriteIndentedColored(5, ConsoleColor.DarkYellow, True, "Command Arguments:")
                        For Each argAttrib As CommandMethodArgumentAttribute In commandMethod.ArgumentAttributes
                            ConsoleOutput.WriteFormatted("\[r6]\[c14]{0}\[c16] {1}\[n]", argAttrib.ArgumentName, argAttrib.FormattedHelpText)
                        Next
                        ConsoleOutput.WriteLine()
                    End If
                    If commandMethod.FormattedHelpText.Length > 0 Then
                        ConsoleOutput.WriteIndentedColored(5, ConsoleColor.DarkYellow, True, "Extended Help:")
                        ConsoleOutput.WriteFormatted("\[r3]" & commandMethod.FormattedHelpText)
                        ConsoleOutput.WriteLine()
                    Else
                        ConsoleOutput.WriteLine("No extended help available.")
                    End If
                Else
                    line.SetResultMessage(CommandInterpreter.UnrecognizedCommandText & ": " & testName, True)
                End If
            Else
                line.SetResultMessage(CommandInterpreter.UnrecognizedCommandText & ": " & testName, True)
            End If
        End If
    End Sub

    <CommandMethod("Outputs text to the console.", "Any text following the \[c9]Echo\[c16] command will be displayed as formatted text in the console.")>
    <CommandMethodArgument("FormattedText", 0, "The formatted text to output.")>
    Public Overridable Sub Echo(line As CommandLine)
        If line.Words.Length > 1 Then
            ConsoleOutput.WriteFormatted(line.Text.Trim.Substring(CommandInterpreter.CommandIndentifierToken.Length + 5))
        End If
    End Sub

    <CommandMethod("Clears the console and command interpreter result list.", "Removes all text from the console, placing the cursor at the top left, and clears the current list of command results.")>
    Public Overridable Sub Clear(line As CommandLine)
        Console.Clear()
        CommandInterpreter.CommandResults.Clear()
    End Sub

    <CommandMethod("Display interpreter log.", "Displays the log entries for all items in the current command result list.")>
    Public Overridable Sub ShowLog(line As CommandLine)
        Dim output As New System.Text.StringBuilder
        For Each entry As LogListEntry In CommandInterpreter.CommandResults.LogEntries
            output.Append(entry.LogEntry.ToFormattedString)
            output.Append("\[n]")
        Next
        ConsoleOutput.WriteFormatted(output.ToString)
    End Sub
End Class
